//! 工具函数测试

use crate::errors::{BinanceError, error_codes};
use crate::models::common::*;

#[cfg(test)]
mod tests {
    use super::*;
    use rust_decimal::Decimal;

    #[test]
    fn test_order_side_to_string() {
        assert_eq!(OrderSide::Buy.to_string(), "BUY");
        assert_eq!(OrderSide::Sell.to_string(), "SELL");
    }

    #[test]
    fn test_order_type_to_string() {
        assert_eq!(OrderType::Limit.to_string(), "LIMIT");
        assert_eq!(OrderType::Market.to_string(), "MARKET");
        assert_eq!(OrderType::StopLoss.to_string(), "STOP_LOSS");
        assert_eq!(OrderType::StopLossLimit.to_string(), "STOP_LOSS_LIMIT");
        assert_eq!(OrderType::TakeProfit.to_string(), "TAKE_PROFIT");
        assert_eq!(OrderType::TakeProfitLimit.to_string(), "TAKE_PROFIT_LIMIT");
        assert_eq!(OrderType::LimitMaker.to_string(), "LIMIT_MAKER");
    }

    #[test]
    fn test_time_in_force_to_string() {
        assert_eq!(TimeInForce::Gtc.to_string(), "GTC");
        assert_eq!(TimeInForce::Ioc.to_string(), "IOC");
        assert_eq!(TimeInForce::Fok.to_string(), "FOK");
        assert_eq!(TimeInForce::Gtx.to_string(), "GTX");
    }

    #[test]
    fn test_order_response_type_to_string() {
        assert_eq!(OrderResponseType::Ack.to_string(), "ACK");
        assert_eq!(OrderResponseType::Result.to_string(), "RESULT");
        assert_eq!(OrderResponseType::Full.to_string(), "FULL");
    }

    #[test]
    fn test_error_codes() {
        assert_eq!(error_codes::UNKNOWN_ORDER, -2011);
        assert_eq!(error_codes::INSUFFICIENT_BALANCE, -2010);
        assert_eq!(error_codes::INVALID_SYMBOL, -1121);
        assert_eq!(error_codes::INVALID_QUANTITY, -1013);
        assert_eq!(error_codes::INVALID_PRICE, -1013);
        assert_eq!(error_codes::TOO_MANY_REQUESTS, -1003);
        assert_eq!(error_codes::REQUEST_THROTTLED, -1008);
        assert_eq!(error_codes::INVALID_API_KEY, -1022);
        assert_eq!(error_codes::INVALID_SIGNATURE, -1021);
        assert_eq!(error_codes::TIMESTAMP_EXPIRED, -1021);
    }

    #[test]
    fn test_binance_error_display() {
        let network_error = BinanceError::NetworkError("Connection failed".to_string());
        assert_eq!(network_error.to_string(), "Network error: Connection failed");

        let http_error = BinanceError::HttpError(404, "Not found".to_string());
        assert_eq!(http_error.to_string(), "HTTP 404 error: Not found");

        let api_error = BinanceError::ApiError(crate::models::BinanceApiError {
            code: -2011,
            msg: "Unknown order sent".to_string(),
        });
        assert_eq!(api_error.to_string(), "API error -2011: Unknown order sent");

        let config_error = BinanceError::ConfigError("Invalid configuration".to_string());
        assert_eq!(config_error.to_string(), "Configuration error: Invalid configuration");

        let serialization_error = BinanceError::SerializationError("JSON parse error".to_string());
        assert_eq!(serialization_error.to_string(), "Serialization error: JSON parse error");

        let parse_error = BinanceError::ParseError("Invalid format".to_string());
        assert_eq!(parse_error.to_string(), "Parse error: Invalid format");

        let other_error = BinanceError::Other("Unknown error".to_string());
        assert_eq!(other_error.to_string(), "Other error: Unknown error");
    }

    #[test]
    fn test_binance_error_methods() {
        let network_error = BinanceError::NetworkError("Connection failed".to_string());
        assert!(network_error.is_network_error());
        assert!(!network_error.is_api_error());
        assert!(!network_error.is_config_error());

        let api_error = BinanceError::ApiError(crate::models::BinanceApiError {
            code: -2011,
            msg: "Unknown order sent".to_string(),
        });
        assert!(!api_error.is_network_error());
        assert!(api_error.is_api_error());
        assert!(!api_error.is_config_error());

        let config_error = BinanceError::ConfigError("Invalid configuration".to_string());
        assert!(!config_error.is_network_error());
        assert!(!config_error.is_api_error());
        assert!(config_error.is_config_error());
    }

    #[test]
    fn test_binance_error_message() {
        let network_error = BinanceError::NetworkError("Connection failed".to_string());
        assert_eq!(network_error.message(), "Connection failed");

        let api_error = BinanceError::ApiError(crate::models::BinanceApiError {
            code: -2011,
            msg: "Unknown order sent".to_string(),
        });
        assert_eq!(api_error.message(), "Unknown order sent");

        let config_error = BinanceError::ConfigError("Invalid configuration".to_string());
        assert_eq!(config_error.message(), "Invalid configuration");
    }

    #[test]
    fn test_binance_error_api_code() {
        let network_error = BinanceError::NetworkError("Connection failed".to_string());
        assert_eq!(network_error.api_code(), None);

        let api_error = BinanceError::ApiError(crate::models::BinanceApiError {
            code: -2011,
            msg: "Unknown order sent".to_string(),
        });
        assert_eq!(api_error.api_code(), Some(-2011));

        let config_error = BinanceError::ConfigError("Invalid configuration".to_string());
        assert_eq!(config_error.api_code(), None);
    }

    #[test]
    fn test_binance_api_error_serialization() {
        let api_error = crate::models::BinanceApiError {
            code: -2011,
            msg: "Unknown order sent".to_string(),
        };

        // 测试序列化
        let serialized = serde_json::to_string(&api_error).unwrap();
        assert!(serialized.contains("-2011"));
        assert!(serialized.contains("Unknown order sent"));

        // 测试反序列化
        let deserialized: crate::models::BinanceApiError = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized.code, api_error.code);
        assert_eq!(deserialized.msg, api_error.msg);
    }

    #[test]
    fn test_error_from_implementations() {
        // 测试从reqwest::Error转换
        let reqwest_error = reqwest::Error::from(std::io::Error::new(std::io::ErrorKind::Other, "test"));
        let binance_error: BinanceError = reqwest_error.into();
        assert!(binance_error.is_network_error());

        // 测试从serde_json::Error转换
        let json_error = serde_json::from_str::<String>("invalid json").unwrap_err();
        let binance_error: BinanceError = json_error.into();
        assert!(matches!(binance_error, BinanceError::SerializationError(_)));

        // 测试从std::io::Error转换
        let io_error = std::io::Error::new(std::io::ErrorKind::Other, "test");
        let binance_error: BinanceError = io_error.into();
        assert!(matches!(binance_error, BinanceError::Other(_)));

        // 测试从url::ParseError转换
        let url_error = url::ParseError::EmptyHost;
        let binance_error: BinanceError = url_error.into();
        assert!(binance_error.is_config_error());

        // 测试从anyhow::Error转换
        let anyhow_error = anyhow::Error::new(std::io::Error::new(std::io::ErrorKind::Other, "test"));
        let binance_error: BinanceError = anyhow_error.into();
        assert!(matches!(binance_error, BinanceError::Other(_)));
    }

    #[test]
    fn test_decimal_handling() {
        // 测试Decimal类型的使用
        let price = Decimal::from_str("50000.123456789").unwrap();
        assert_eq!(price.to_string(), "50000.123456789");

        let quantity = Decimal::from_str("0.001").unwrap();
        assert_eq!(quantity.to_string(), "0.001");

        // 测试Decimal的序列化
        let serialized = serde_json::to_string(&price).unwrap();
        assert_eq!(serialized, "\"50000.123456789\"");

        // 测试Decimal的反序列化
        let deserialized: Decimal = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, price);
    }

    #[test]
    fn test_enum_serialization() {
        // 测试OrderSide序列化
        let buy_side = OrderSide::Buy;
        let serialized = serde_json::to_string(&buy_side).unwrap();
        assert_eq!(serialized, "\"BUY\"");

        let deserialized: OrderSide = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, OrderSide::Buy);

        // 测试OrderType序列化
        let limit_type = OrderType::Limit;
        let serialized = serde_json::to_string(&limit_type).unwrap();
        assert_eq!(serialized, "\"LIMIT\"");

        let deserialized: OrderType = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, OrderType::Limit);

        // 测试TimeInForce序列化
        let gtc_tif = TimeInForce::Gtc;
        let serialized = serde_json::to_string(&gtc_tif).unwrap();
        assert_eq!(serialized, "\"GTC\"");

        let deserialized: TimeInForce = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, TimeInForce::Gtc);
    }
}
